﻿#region zh-CHS 2006 - 2007 DemoSoft 团队 | en 2006 - 2007 DemoSoft Team

//     NOTES
// ---------------
//
// This file is a part of the G.O.S.E(Game Online Server Engine) for .NET.
//
//                 2006-2007 DemoSoft Team
//
//
// First Version : by H.Q.Cai - mailto:caihuanqing@hotmail.com

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

#region zh-CHS 包含名字空间 | en Include namespace
using System;
using System.Net;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Demo_G.O.S.E.ServerEngine;
using Demo_G.O.S.E.ServerEngine.Util;
using Demo_G.O.S.E.ServerEngine.World;
using Demo_G.O.S.E.ServerEngine.Timer;
using Demo_G.O.S.E.ServerEngine.Common;
using Demo_G.O.S.E.ServerEngine.Server;
using Demo_G.O.S.E.ServerEngine.Mobile;
using Demo_G.O.S.E.ServerEngine.Network.DLL;
#endregion

namespace Demo_G.O.S.E.ServerEngine.Network
{
    /// <summary>
    /// 网络的主状态
    /// </summary>
    [MultiThreadedSupportgAttribute( "当前的类所有成员都可锁定,支持多线程操作" )]
    public class NetState
    {
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 消息处理的类
        /// </summary>
        private MessagePump m_MessagePump = null;
        #endregion

        #region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
        /// <summary>
        /// 有实例产生时调用
        /// </summary>
        /// <param name="clientSocket"></param>
        /// <param name="messagePump"></param>
        private NetState( ClientSocketHandler clientSocket, MessagePump messagePump )
        {
            ReInitNetState( clientSocket, messagePump );
        }

        /// <summary>
        /// 重新有实例产生时调用
        /// </summary>
        /// <param name="clientSocket"></param>
        /// <param name="messagePump"></param>
        private void ReInitNetState( ClientSocketHandler clientSocket, MessagePump messagePump )
        {
            m_Socket = clientSocket;
            m_MessagePump = messagePump;
            m_ConnectedOn = DateTime.Now;
            m_BaseWorld = messagePump.BaseWorld;
            m_ToString = clientSocket.ClientAddress;
            m_NextCheckActivity = m_ConnectedOn + TimeSpan.FromMinutes( 0.5 );

            IPAddress.TryParse( clientSocket.RemoteOnlyIP, out m_NetAddress );

            m_Seed = null;
            m_Encoder = null;
            m_Version = null;
            m_ExtendData = null;
            m_BaseMobile = null;

            m_Running = false;
            m_BlockSend = false;
            m_Disposing = false;
            m_bCheckAlive = true;
            m_IsInProcessQueue = false;

            // 静态
            if ( EventCreatedCallback != null )
                EventCreatedCallback( this );

            //  非静态
            if ( EventConnected != null )
                EventConnected( this );
        }
        #endregion

        #region zh-CHS 共有属性 | en Public Properties
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 客户开始连接的时间
        /// </summary>
        private DateTime m_ConnectedOn  = DateTime.Now;
        #endregion
        /// <summary>
        /// 客户开始连接的时间
        /// </summary>
        public DateTime ConnectedOn
        {
            get { return m_ConnectedOn; }
        }

        /// <summary>
        /// 客户总共连接的时间
        /// </summary>
        public TimeSpan ConnectedFor
        {
            get { return (DateTime.Now - m_ConnectedOn); }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 客户的地址
        /// </summary>
        private IPAddress m_NetAddress = IPAddress.None;
        #endregion
        /// <summary>
        /// 客户的地址
        /// </summary>
        public IPAddress NetAddress
        {
            get { return m_NetAddress; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 加解密的数据包
        /// </summary>
        private IPacketEncoder m_Encoder    = null;
        #endregion
        /// <summary>
        /// 加解密的数据包接口
        /// </summary>
        public IPacketEncoder PacketEncoder
        {
            get { return m_Encoder; }
            set { m_Encoder = value; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 是否阻塞全部的包
        /// </summary>
        private bool m_BlockSend = false;
        #endregion
        /// <summary>
        /// 是否阻塞全部的包,不发送
        /// </summary>
        public bool BlockSend
        {
            get { return m_BlockSend; }
            set { m_BlockSend = value; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 客户是否在运行
        /// </summary>
        private bool m_Running = false;
        #endregion
        /// <summary>
        /// 客户是否在运行, 如果没有表示已经断开了连接
        /// </summary>
        public bool Running
        {
            get { return m_Running; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 网络句柄
        /// </summary>
        private ClientSocketHandler m_Socket = null;
        /// <summary>
        /// 网络句柄的锁
        /// </summary>
        private object m_LockSocket = new object();
        #endregion
        /// <summary>
        /// 客户端连接的句柄
        /// </summary>
        public ClientSocketHandler NetSocket
        {
            get { return m_Socket; }
        }

        /// <summary>
        /// 接收到的环形缓冲区
        /// </summary>
        public ReceiveQueue ReceiveBuffer
        {
            get { return m_Socket == null ? null : m_Socket.Buffer; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 客户端的版本号
        /// </summary>
        private ClientVersion m_Version = null;
        #endregion
        /// <summary>
        /// 客户端的版本号
        /// </summary>
        public ClientVersion Version
        {
            get { return m_Version; }
            set { m_Version = value; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 可填充得扩展数据
        /// </summary>
        private object m_ExtendData = null;
        #endregion
        /// <summary>
        /// 可填充得扩展数据
        /// </summary>
        public object ExtendData
        {
            get { return m_ExtendData; }
            set { m_ExtendData = value; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 加解密的数据种子
        /// </summary>
        private byte[] m_Seed = null;
        #endregion
        /// <summary>
        /// 加解密的数据种子
        /// </summary>
        public byte[] EncoderSeed
        {
            get { return m_Seed; }
            set { m_Seed = value; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 人物
        /// </summary>
        private BaseMobile m_BaseMobile = null;
        #endregion
        /// <summary>
        /// 人物
        /// </summary>
        public BaseMobile Mobile
        {
            get { return m_BaseMobile; }
            set { m_BaseMobile = value; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 是否检查网络活动
        /// </summary>
        private bool m_bCheckAlive = true;
        #endregion
        /// <summary>
        /// 是否检查网络活动
        /// </summary>
        public bool IsCheckActivity
        {
            get { return m_bCheckAlive; }
            set { m_bCheckAlive = value; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 管理当前的世界服务
        /// </summary>
        private BaseWorld m_BaseWorld = null;
        #endregion
        /// <summary>
        /// 管理当前的世界服务
        /// </summary>
        public BaseWorld BaseWorld
        {
            get { return m_BaseWorld; }
        }
        #endregion

        #region zh-CHS 共有静态属性 | en Public Static Properties
        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 检查在线的时间
        /// </summary>
        private static TimeSpan s_CheckAliveTime = TimeSpan.FromMinutes( 5.0 );
        #endregion
        /// <summary>
        /// 检查在线的时间
        /// </summary>
        public static TimeSpan CheckAliveTime
        {
            get { return s_CheckAliveTime; }
            set { s_CheckAliveTime = value; }
        }
        #endregion

        #region zh-CHS 内部方法 | en Internal Method
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 第一次处理数据包的时间片
        /// </summary>
        private TimeSlice m_TimeSliceCheckFirst = null;
        #endregion
        /// <summary>
        /// 开始运行客户端的处理
        /// </summary>
        internal void Start()
        {
            // 保存副本 防止多线程时有问题(m_Socket可能已置空)
            ClientSocketHandler l_Socket = m_Socket;
            if ( m_Socket == null || m_Running || m_Disposing )
                return;
            else
            {
                m_Running = true;
                m_BaseWorld.AddNetState( this );
            }

            l_Socket.EventThreadProcessMessageBlock += new EventDelegateClientHandlerProcessMessageBlock( OnProcessMessageBlock );
            l_Socket.EventThreadDisconnect += new EventDelegateClientHandlerDisconnect( OnDisconnect );

            if ( l_Socket.Adding > 0 )
                OnProcessMessageBlock( null );
            else
            {
                // 如果是第一次处理数据包,则发送的那次全局信号
                // 可能还来不及处理数据包,会产生无法处理第一个数据包的问题BUG
                // 可能产生原因是信号已发送并处理过,但是数据还可能还没有压入环形缓冲区
                if ( m_TimeSliceCheckFirst == null )
                    m_TimeSliceCheckFirst = TimeSlice.DelayCall( TimeSpan.FromSeconds( 0.50 ), TimeSpan.FromSeconds( 1.0 ), new TimeSliceCallback( CheckFirstReceiveBuffer ) );

                if ( m_TimeSliceCheckFirst.Running  == false )
                    m_TimeSliceCheckFirst.Start();
            }
        }

        #region zh-CHS 时间片的回调函数 | en TimeSlice
        /// <summary>
        /// 第一次处理数据包
        /// </summary>
        private void CheckFirstReceiveBuffer( )
        {
            // 保存副本 防止多线程时有问题(m_Socket可能已置空)
            ClientSocketHandler l_Socket = m_Socket;
            if ( m_Socket == null )
            {
                m_TimeSliceCheckFirst.Stop();
                return;
            }

            // 数据包已进入环绕缓冲区
            if ( l_Socket.Adding > 0 )
            {
                m_TimeSliceCheckFirst.Stop();

                OnProcessMessageBlock( null );
            }
        }
        #endregion

        /// <summary>
        /// 发送缓存的数据
        /// </summary>
        /// <returns>是否成功处理缓存的发送</returns>
        internal bool Flush()
        {
            if ( m_SendQueue.IsFlushReady == false )
                return false;

            // 保存副本 防止多线程时有问题(m_Socket可能已置空)
            ClientSocketHandler l_Socket = m_Socket;
            if ( m_Socket == null || m_BlockSend )
                return false;

            ACESocketHandlerManagerAtServer l_SocketHandlerManagerAtServer = l_Socket.SocketHandlerManager;
            if ( l_SocketHandlerManagerAtServer == null )
            {
                Debug.WriteLine( "NetState.Flush(...) - l_SocketHandlerManagerAtServer == null error!" );
                return false;
            }

            SendQueue.Gram sendGram = m_SendQueue.FlushReady();
            if ( sendGram != null )
            {
                ACEMessageBlock l_MessageBlock = l_SocketHandlerManagerAtServer.GetNewSendMessageBlock();
                if ( l_MessageBlock == null )
                {
                    Debug.WriteLine( "NetState.Flush(...) - l_MessageBlock == null error!" );
                    return false;
                }

                Marshal.Copy( sendGram.Buffer, 0, l_MessageBlock.WriteIntPtr(), (int)sendGram.Length );
                l_MessageBlock.WriteIntPtrLength( (int)sendGram.Length );

                l_Socket.SendTo( l_MessageBlock );
            }

            return true;
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 检查是否在线的时间段
        /// </summary>
        private DateTime m_NextCheckActivity    = DateTime.Now;
        #endregion
        /// <summary>
        /// 检查用户是否在线,根据用户传输数据包的时间来判定
        /// </summary>
        /// <returns></returns>
        internal bool CheckAlive()
        {
            if ( m_Socket == null || m_Running == false || m_Disposing )
                return false;

            if ( m_bCheckAlive == false || DateTime.Now < m_NextCheckActivity )
                return true;

            Dispose();

            LOGs.WriteLine( LogMessageType.MSG_NOTICE, "连接检查: {0}已不再活动,断开客户...", this );

            return false;
        }

        /// <summary>
        /// 显示当前客户端的内容信息
        /// </summary>
        /// <param name="strText"></param>
        internal void LogWriteLine( string strText )
        {
            LOGs.WriteLine( LogMessageType.MSG_INFO, "客户端: {0} {1}", this, strText );
        }

        /// <summary>
        /// 显示当前客户端的内容信息
        /// </summary>
        /// <param name="strFormat"></param>
        /// <param name="strArgs"></param>
        internal void LogWriteLine( string strFormat, params object[] strArgs )
        {
            LOGs.WriteLine( LogMessageType.MSG_INFO, strFormat, strArgs );
        }
        #endregion

        #region zh-CHS 共有方法 | en public Method
        #region zh-CHS 内部SendQueue属性 | en Internal SendQueue Properties
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 发送数据的集合
        /// </summary>
        private SendQueue m_SendQueue = new SendQueue();
        #endregion
        /// <summary>
        /// 发送数据的集合
        /// </summary>
        internal SendQueue SendQueue
        {
            get { return m_SendQueue; }
        }
        #endregion
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="packet">需要发送的数据包</param>
        public virtual void Send( Packet packet )
        {
            // 保存副本 防止多线程时有问题(m_Socket可能已置空)
            ClientSocketHandler l_Socket = m_Socket;
            if ( m_Socket == null || m_Disposing || m_BlockSend )
            {
                // 表示已处理发送
                packet.Release();
                return;
            }

            long l_iLength = 0;

            PacketProfile l_PacketProfile = PacketProfile.GetOutgoingProfile( (byte)packet.PacketID );
            DateTime l_DateTimeStart = ( l_PacketProfile == null ? DateTime.MinValue : DateTime.Now );
            {
                bool l_bIsNoError = true;
                bool l_bIsFlush = false;
                do
                {
                    byte[] l_byteBuffer = packet.AcquireCompile( false, out l_iLength ); // R.O.S.E 不需要压缩的
                    if ( l_byteBuffer == null )
                    {
                        Debug.WriteLine( "NetState.Send(...) - byteBuffer == null error!" );

                        l_bIsNoError = false;
                        break; // 错误
                    }

                    if ( l_byteBuffer.Length <= 0 || l_iLength <= 0 )
                    {
                        Debug.WriteLine( "NetState.Send(...) - byteBuffer.Length <= 0 || iLength <= 0 error!" );

                        l_bIsNoError = false;
                        break; // 错误
                    }

                    if ( m_Encoder != null )
                        m_Encoder.EncodeOutgoingPacket( this, ref l_byteBuffer, ref l_iLength ); // 加密数据 R.O.S.E不需要

                    ACESocketHandlerManagerAtServer l_SocketHandlerManagerAtServer = l_Socket.SocketHandlerManager;
                    if ( l_SocketHandlerManagerAtServer == null )
                    {
                        Debug.WriteLine( "NetState.Send(...) - l_SocketHandlerManagerAtServer == null error!" );

                        l_bIsNoError = false;
                        break; // 错误
                    }

                    //////////////////////////////////////////////////////////////////////////
                    using ( System.IO.StreamWriter streamWriter = new System.IO.StreamWriter( "Out_Packets.log", true ) )
                    {
                        byte[] byteBufferTemp = l_byteBuffer;

                        if ( byteBufferTemp.Length > 0 )
                        {
                            streamWriter.WriteLine( "客户端:  {0}  发送加密的信息包 长度 = 0x{1:X4} ID = 0x{2:X4}", 0, l_iLength, packet.PacketID );
                            streamWriter.WriteLine( "--------------------------------------------------------------------------" );
                        }

                        using ( System.IO.MemoryStream memoryStream = new System.IO.MemoryStream( byteBufferTemp ) )
                            Utility.FormatBuffer( streamWriter, memoryStream, l_iLength );

                        streamWriter.WriteLine();
                        streamWriter.WriteLine();
                    }
                    //////////////////////////////////////////////////////////////////////////

                    SendQueue.Gram sendGram = m_SendQueue.Enqueue( l_byteBuffer, l_iLength );
                    if ( sendGram == null ) // 返回空说明需要Flush(...)时发送数据
                    {
                        l_bIsFlush = true;
                        break;
                    }

                    while ( sendGram != null )
                    {
                        ACEMessageBlock l_MessageBlock = l_SocketHandlerManagerAtServer.GetNewSendMessageBlock();
                        if ( l_MessageBlock == null )
                        {
                            Debug.WriteLine( "NetState.Send(...) - l_MessageBlock == null error!" );

                            l_bIsNoError = false;
                            break; // 错误
                        }

                        Marshal.Copy( sendGram.Buffer, 0, l_MessageBlock.WriteIntPtr(), (int)sendGram.Length );
                        l_MessageBlock.WriteIntPtrLength( (int)sendGram.Length );

                        l_Socket.SendTo( l_MessageBlock );

                        // 再次获取数据
                        sendGram = m_SendQueue.Dequeue();
                    }
                } while ( false );

                // 表示已处理发送
                packet.Release();

                if ( l_bIsNoError && l_bIsFlush  && m_BaseWorld != null )
                    m_BaseWorld.FlushNetStates( this );
            }
            if ( l_PacketProfile != null )
                l_PacketProfile.Record( l_iLength, DateTime.Now - l_DateTimeStart );
        }

        #region zh-CHS 私有常量 | en Private Constants
        /// <summary>
        /// 
        /// </summary>
        private const int DISCONNECT_SECOND = 5;
        #endregion
        /// <summary>
        /// 清理当前的网络数据,并断开连接(Flush == true 则默认5秒以后断开)
        /// </summary>
        /// <param name="bFlush"></param>
        public virtual void Dispose()
        {
            Dispose( true, DISCONNECT_SECOND );
        }

        /// <summary>
        /// 清理当前的网络数据,并断开连接(如果 bFlush == true 则默认5秒以后断开)
        /// </summary>
        /// <param name="bFlush"></param>
        public virtual void Dispose( bool bFlush )
        {
            Dispose( bFlush, DISCONNECT_SECOND );
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 表示是否已经Dispose(...)过了
        /// </summary>
        private bool m_Disposing    = false;
        #endregion
        /// <summary>
        /// 清理当前的网络数据,并断开连接
        /// </summary>
        /// <param name="bFlush"></param>
        public virtual void Dispose( bool bFlush, long iSeconds )
        {
            if ( m_Socket == null || m_Disposing )
                return;

            m_Running = false;
            m_Disposing = true;

            if ( bFlush )
            {
                Flush();

                TimeSlice.DelayCall( TimeSpan.FromSeconds( iSeconds ), new TimeSliceCallback( InsideDispose ) );
            }
            else InsideDispose();
        }

        #region zh-CHS 私有 InsideDispose 方法 | en Private InsideDispose Methods
        /// <summary>
        /// 断开连接
        /// </summary>
        private void InsideDispose()
        {
            try
            {
                // 保存副本 防止多线程时有问题(m_Socket可能已置空)
                ClientSocketHandler l_Socket = m_Socket;
                if ( m_Socket == null )
                {
                    Debug.WriteLine( "NetState.InsideDispose(...) - m_Socket == null error!" );

                    return;
                }
                else
                    l_Socket.CloseSocket();
            }
            catch { }
        }
        #endregion

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 当前实例的IP地址字符串
        /// </summary>
        private string m_ToString = string.Empty;
        #endregion
        /// <summary>
        /// 当前实例的IP地址字符串
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return m_ToString;
        }
        #endregion

        #region zh-CHS 内部静态方法 | en Internal Static Method
        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// NetState实例池
        /// </summary>
        private static Queue<NetState> s_NetStatePool = new Queue<NetState>();
        /// <summary>
        /// 锁
        /// </summary>
        private static object s_LockNetStatePool = new object();
        #endregion
        /// <summary>
        /// 给出实例
        /// </summary>
        /// <param name="clientSocket"></param>
        /// <param name="messagePump"></param>
        /// <returns></returns>
        internal static NetState Instance( ClientSocketHandler clientSocket, MessagePump messagePump )
        {
            NetState netState = null;

            Monitor.Enter( s_LockNetStatePool );
            {
                if ( s_NetStatePool.Count > 0 )
                    netState = s_NetStatePool.Dequeue();
            }
            Monitor.Exit( s_LockNetStatePool );

            if ( netState == null )
                netState = new NetState( clientSocket, messagePump );
            else
                netState.ReInitNetState( clientSocket, messagePump );

            return netState;
        }

        /// <summary>
        /// 释放入内存池
        /// </summary>
        internal void Release()
        {
            Monitor.Enter( NetState.s_LockNetStatePool );
            {
                s_NetStatePool.Enqueue( this );
            }
            Monitor.Exit( NetState.s_LockNetStatePool );
        }
        #endregion

        #region zh-CHS 私有的事件处理函数 | en Private Event Handlers
        /// <summary>
        /// 
        /// </summary>
        /// <param name="RecvMessageBlock"></param>
        private void OnProcessMessageBlock( ACEMessageBlock RecvMessageBlock )
        {
            if ( m_Socket == null )
            {
                Debug.WriteLine( "NetState.OnProcessMessageBlock(...) - m_Socket == null error!" );

                return;
            }

            m_NextCheckActivity = DateTime.Now + s_CheckAliveTime;

            if ( m_MessagePump != null )
                m_MessagePump.OnReceive( this );
            else
                Debug.WriteLine( "NetState.OnProcessMessageBlock(...) - m_MessagePump == null error!" );
        }

        /// <summary>
        /// 调用ClientSocketHandler.CloseSocket(...)的时候会产生此调用
        /// </summary>
        private void OnDisconnect()
        {
            // 保存副本 防止多线程时有问题(m_Socket可能已置空)
            ClientSocketHandler l_Socket = m_Socket;
            if ( m_Socket == null )
            {
                Debug.WriteLine( "NetState.OnDisconnect(...) - m_Socket == null error!" );

                return;
            }
            else
            {
                m_Socket = null;
                m_Running = false;
                m_Disposing = true;
            }

            l_Socket.EventThreadProcessMessageBlock -= new EventDelegateClientHandlerProcessMessageBlock( OnProcessMessageBlock );
            l_Socket.EventThreadDisconnect -= new EventDelegateClientHandlerDisconnect( OnDisconnect );
            l_Socket.InternalDisconnect();

            // 如果还存在需要发送的数据,则直接清空
            if ( m_SendQueue.IsEmpty == false )
                m_SendQueue.Clear(); // 内部已经有锁定

            // 断开的通知事件
            if ( EventDisconnect != null )
                EventDisconnect( this );

            // 放入无效客户端的集合内,等待处理
            if ( m_BaseWorld != null )
                m_BaseWorld.DisposedNetStates( this );

            LOGs.WriteLine( LogMessageType.MSG_INFO, "断开连接: {0} 已经断开连接", this );
        }
        #endregion

        #region zh-CHS 共有事件 | en Public Event
        /// <summary>
        /// 当网络连接时调用
        /// </summary>
        [MultiThreadedWarningAttribute( "此处会在不同的线程内回调:(多线程)警告!" )]
        public event ConnectedNetStateEventHandler EventConnected;
        /// <summary>
        /// 当网络断开时调用
        /// </summary>
        [MultiThreadedWarningAttribute( "此处会在不同的线程内回调:(多线程)警告!" )]
        public event DisconnectNetStateEventHandler EventDisconnect;
        #endregion

        #region zh-CHS 共有静态事件 | en Public Static Event
        /// <summary>
        /// 当创建一个新的NetState时的回调
        /// </summary>
        public static event CreatedNetStateEventHandler EventCreatedCallback;
        #endregion

        #region zh-CHS Process Queue 方法 | en Process Queue Methods

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 表示当前已加入在处理列表中
        /// </summary>
        private bool m_IsInProcessQueue = false;
        /// <summary>
        /// 表示当前已加入在处理列表中的锁
        /// </summary>
        private object m_LockIsInProcessQueue = new object();
        #endregion
        /// <summary>
        /// 检查当前是否已加入在处理列表中
        /// </summary>
        /// <returns></returns>
        internal bool IsInProcessQueue()
        {
            return m_IsInProcessQueue;
        }

        /// <summary>
        /// 表示当前已加入在处理列表中(减少处理列表的长度)
        /// </summary>
        internal void InProcessQueue()
        {
            Monitor.Enter( m_LockIsInProcessQueue );
            {
                m_IsInProcessQueue = true;
            }
            Monitor.Exit( m_LockIsInProcessQueue );
        }

        /// <summary>
        /// 表示当前已不再处理列表中(减少处理列表的长度)
        /// </summary>
        internal void OutProcessQueue()
        {
            Monitor.Enter( m_LockIsInProcessQueue );
            {
                m_IsInProcessQueue = false;
            }
            Monitor.Exit( m_LockIsInProcessQueue );
        }
        #endregion

        #region zh-CHS Flush Queue 方法 | en Flush Queue Methods

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 表示当前已加入在处理列表中
        /// </summary>
        private bool m_IsInFlushQueue = false;
        /// <summary>
        /// 表示当前已加入在处理列表中的锁
        /// </summary>
        private object m_LockIsInFlushQueue = new object();
        #endregion
        /// <summary>
        /// 检查当前是否已加入在处理列表中
        /// </summary>
        /// <returns></returns>
        internal bool IsInFlushQueue()
        {
            return m_IsInFlushQueue;
        }

        /// <summary>
        /// 表示当前已加入在处理列表中(减少处理列表的长度)
        /// </summary>
        internal void InFlushQueue()
        {
            Monitor.Enter( m_LockIsInFlushQueue );
            {
                m_IsInFlushQueue = true;
            }
            Monitor.Exit( m_LockIsInFlushQueue );
        }

        /// <summary>
        /// 表示当前已不再处理列表中(减少处理列表的长度)
        /// </summary>
        internal void OutFlushQueue()
        {
            Monitor.Enter( m_LockIsInFlushQueue );
            {
                m_IsInFlushQueue = false;
            }
            Monitor.Exit( m_LockIsInFlushQueue );
        }
        #endregion
    }
}
#endregion

